package com.bjpowernode.mvc.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bjpowernode.common.client.RedisClient;
import com.bjpowernode.common.constant.RedisKey;
import com.bjpowernode.db.domain.BidInfo;
import com.bjpowernode.db.domain.ProductInfo;
import com.bjpowernode.db.mapper.BidInfoMapper;
import com.bjpowernode.db.mapper.ProductInfoMapper;
import com.bjpowernode.db.mapper.SysUserMapper;
import com.bjpowernode.mvc.model.dto.AppDTO;
import com.bjpowernode.mvc.service.inter.AppService;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

/**
 * @RequiredArgsConstructor注解：创建有参构造方法 给final类型的成员变量创建构造方法，在构造方法中给引用类型赋值
 */
@RequiredArgsConstructor
@Service
public class AppServiceImpl implements AppService {

    //推荐使用构造注入：使用构造方法给引用类型赋值
    //目的：保证每个引用类型都必须赋值成功，这个对象才可以正常使用
    private final ProductInfoMapper productInfoMapper;
    private final BidInfoMapper bidInfoMapper;
    private final SysUserMapper sysUserMapper;

    private final RedisClient redisClient;


    /**
     * 统计平台三项数据
     * 1、从Redis中获取数据
     * 2、如果有数据，直接返回给Controller
     * 3、Redis没有数据，则直接查询数据库
     * 4、查询之后，将数据存入到Redis中
     * 5、返回查询的结果对象
     *
     * @return
     */
    @Override
    public AppDTO getAppInfo() {
        AppDTO appDTO;
        //1、从Redis中获取数据
        String val = redisClient.getVal(RedisKey.APP_BASE_INFO);
        if (StrUtil.isNotEmpty(val)) {
            //如果Redis不为空
            appDTO = JSONUtil.toBean(val, AppDTO.class);
        } else {
            //Redis中没有值
            synchronized (this) {
                val = redisClient.getVal(RedisKey.APP_BASE_INFO);
                if (StrUtil.isNotEmpty(val)) {
                    //如果Redis不为空
                    appDTO = JSONUtil.toBean(val, AppDTO.class);
                } else {
                    //2、查询数据库
                    appDTO = queryBaseInfoFromDB();
                    //3、存到Redis
                    redisClient.setVal(RedisKey.APP_BASE_INFO, JSONUtil.toJsonStr(appDTO), 60, TimeUnit.MINUTES);
                }
            }
        }
        return appDTO;
    }

    private AppDTO queryBaseInfoFromDB() {
        //1.注册用户数量
        Long userCount = sysUserMapper.selectCount(null);

        //2.累计成交金额
        QueryWrapper<BidInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("IFNULL(sum(bid_money), 0) as bid_money");
        BidInfo bidInfo = bidInfoMapper.selectOne(queryWrapper);
        BigDecimal sumBidMoney = bidInfo.getBidMoney();

        //3.历史年化收益率  round函数:保留几位有效小数  rate产品利率
        QueryWrapper<ProductInfo> wrapper = new QueryWrapper<>();
        wrapper.select("ROUND(IFNULL(avg(rate), 0), 2) as rate");
        ProductInfo productInfo = productInfoMapper.selectOne(wrapper);
        BigDecimal productAvgRate = productInfo.getRate();

        //构造器
        return new AppDTO(productAvgRate, sumBidMoney, userCount);
    }
}
